package ch.simplix.android.repetitive.implementation;

import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import android.util.Log;
import ch.simplix.android.repetitive.definition.RepeaterAction;
import ch.simplix.android.repetitive.definition.RepeaterStrategy;

/**
 * This class serves as facade in order to process repetitive tasks. There are
 * different strategies for repetition, some are accurate or fast but cost
 * energy, some are not as accurate or slow but preserve energy.
 * 
 * 
 * @author SimpliX
 * 
 */
public class RepetitiveContextFacade {
	private static final String TAG = "RepetitiveContextFacade";

	private static final String STRATEGY_SLEEP = "sleep";
	private static final String STRATEGY_ARLARM_RTC = "alarm_rtc";
	private HashMap<String, RepeaterStrategy> repeaterStrategies;
	private String activeStrategy;
	private RepeaterAction repeaterAction;
	

	public RepetitiveContextFacade(RepeaterAction repeaterAction) {
		this.repeaterAction = repeaterAction;		
		repeaterStrategies = new HashMap<String, RepeaterStrategy>();
		repeaterStrategies.put(STRATEGY_ARLARM_RTC, new AlarmRepeaterStrategy(
				repeaterAction));
		repeaterStrategies.put(STRATEGY_SLEEP, new SleepRepeaterStrategy(
				repeaterAction));
		activeStrategy = STRATEGY_SLEEP;
	}

	public boolean isRunning() {
		return repeaterStrategies.get(activeStrategy).isRunning();
	}

	/**
	 * Start repeating the action- after the time specified
	 */
	public void startTimedRepetition() {
		WakeLockManager.setup(repeaterAction.getContext());
		try {						
				WakeLockManager.s_acquire();
				new Thread() {
					@Override
					public void run() {
						try {
							WakeLockManager.s_acquire();							
							repeaterAction.onRepeat();							
						} finally {
							WakeLockManager.s_release();
						}

					}
				}.start();			
		} finally {
			WakeLockManager.s_release();
		}		
	}

	/**
	 * Stop repeating the action.
	 */
	public void stopTimedRepetition() {
		repeaterStrategies.get(activeStrategy).stopTimedRepetition();
	}

	public void setUpdateInterval(long updateInterval, TimeUnit unit) {
		RepeaterStrategy active = repeaterStrategies.get(activeStrategy);
		if(active!=null&&active.getUpdateIntervalInMillis()==unit.toSeconds(updateInterval)){
			return;
		}
		String activating = null;
		if (unit.toSeconds(updateInterval) < 10) {
			activating = STRATEGY_SLEEP;
		} else {
			activating = STRATEGY_ARLARM_RTC;
		}		
		repeaterStrategies.get(activating).setUpdateInterval(active.getLatestRepetitionInMillis(),updateInterval,
				unit);

		if (!active.equals(repeaterStrategies.get(activating))) {
			if (repeaterStrategies.get(activeStrategy).isRunning()) {
				repeaterStrategies.get(activeStrategy).stopTimedRepetition();
				repeaterStrategies.get(activating).startTimedRepetition();
			}
			activeStrategy = activating;
		}

	}

	public long getUpdateIntervalInMillis() {
		return repeaterStrategies.get(activeStrategy)
				.getUpdateIntervalInMillis();
	}

	@Override
	public void finalize() {
		for (RepeaterStrategy strategy : repeaterStrategies.values()) {
			strategy.finalize();
		}
	}

}
